Repository navigation
feat(sync): restore missing files and archive only with detach --archive - #857
Conversation
|
Review notes. I made no code changes. 1. Medium: you cannot safely rerun
Effect: archive runs before 2. Low: The confirm prompt only asks 3. Inherited from #856: first sync with no Because the baseline falls back to the shared remote manifest when there is no lock, the new "missing file means restore" rule pulls variations from other branches into this branch (checked with a scratch test: |
tonytrinh3
left a comment
There was a problem hiding this comment.
@ctawiah Overall it looks good to me. Devin pointed out additional tests that needed to be added.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4b72020. Configure here.
A missing local file made sync archive the variation in LaunchDarkly. A file is often missing only because the working copy does not have it yet, for example after a Git pull or a branch switch. A plain sync could then archive a variation that other engineers use. Sync now restores a missing file from LaunchDarkly. The sync plan never archives a variation. "ldcli sync prompt detach --archive" is the only way to archive one. It archives each selected variation, and then stops syncing it. It asks for confirmation, and with --no-input it needs --yes. The archive runs first, and an archived variation does not fail, so the same command can run again after a later step fails. The confirmation prompt moves to the interactive package, so that sync and detach use the same prompt.
A restored variation file lost its link to the prompt file that it used. The lock now records the link of each variation, and a restore keeps it. Sync stops with a clear error, and writes nothing, when it cannot restore the link safely. This happens when the working copy has no sync.lock, when the linked file is not available, or when the linked file has local edits. Detach now reads each variation before it archives it, because the API rejects the archive of an archived variation. A rerun after a failed step skips the variations that are already archived and finishes. Detach also uses the command context, so a canceled command does not archive. The lock no longer stores the remote version of each entry. Each save still sends the version that sync read, so optimistic locking does not change. A lock entry now changes only when its content or its link changes, which keeps Git diffs and merge conflicts small. New tests cover linked restores, unsafe restores, a partial failure with several variations, a failed delete followed by a rerun, the interactive archive confirmation, and detach --archive through the CLI.
Every other ldcli resource command uses a plural noun, such as flags, projects, and segments. The command also syncs every prompt variation in the workspace, not one. "ldcli sync prompts" now replaces "ldcli sync prompt", with no alias.
The remote manifest is shared by every branch. A working copy without sync.lock used it as its baseline, so variations from other branches looked tracked and missing. Sync then restored or archived them. Now a missing sync.lock gives an empty baseline. The first sync adopts the local files and writes the lock. This removes the HasLockFile flag, the lock write on a sync without changes, and the restore error for a working copy without sync.lock.
The conflict choice opened in the terminal's alternate screen. That screen hid the diff that sync writes just before the question, so the user saw only the three choices. The conflict choice now shows below the current output, and the diff stays above it. The project, config, and model config pickers keep the full screen, because their lists can be long.
fb0cf44 to
3d1afe5
Compare

Context
A missing local file made sync archive the variation in LaunchDarkly. A file is often missing only because the working copy does not have it yet, for example after a Git pull or a branch switch. A plain sync, or a watch session that applies changes, could then archive a variation that other engineers use.
This PR is stacked on #856. That PR makes
sync.locktrack every project, so sync can find a variation whose file is missing.What changes
archive_serveraction is removed.ldcli sync prompts detach <selector> --archiveis the only way to archive a variation. It archives each selected variation in LaunchDarkly, and then stops syncing it.detach --archiveasks for confirmation in a terminal. With--no-input, it needs--yes, the same rule as other destructive changes.interactivepackage, so sync and detach use one copy.ldcli sync prompts, plural, like the other resource commands. There is no alias forsync prompt.Stop syncing a variation and archive it:
Review focus
detach --archivearchives?detach --archivesafe when a step fails: archive, then baseline, then file deletion?--no-input?Verification
go build ./...go vet ./...go test -race ./internal/sync/... ./cmd/sync/...TestPromptRestoresTrackedMissingFileInsteadOfArchivingdeletes a tracked file, runs sync, and checks that the file comes back and nothing is archived.Related changes
sync.lockdetach --archiveNote
Overview
Sync no longer archives missing local variations. A missing managed file (e.g. after
git pullor branch switch) is treated as restore from LaunchDarkly instead of pushing an archive. Thearchive_serverplan action and related conflict/diff paths are removed; server-side archive is only via detach.ldcli sync prompts detach --archiveoptionally archives selected variations in LaunchDarkly before stopping sync. Archive runs first (idempotent if already archived), then baseline and local cleanup; terminal confirmation or--yeswith--no-input. Sharedinteractive.Confirmpowers sync apply and detach archive prompts; conflict resolution usesSelectInlineso prior output stays visible.CLI rename:
sync prompt→sync prompts(examples/tests updated; no alias).Baseline /
sync.lock: Copies without a lock file no longer inherit the remote manifest as their baseline (avoids tracking other branches’ entries).versionis not written tosync.lock(versions stay on the remote manifest for optimistic updates).reffor linked variations is stored in the lock and used when recreating missing wrapper files; restore fails safely if the linked file is missing or diverges.Breaking: Scripts using
ldcli sync promptmust switch tosync prompts. Behavior change: deleting a tracked file and running sync restores it rather than archiving in LD.Reviewed by Cursor Bugbot for commit 3d1afe5. Bugbot is set up for automated code reviews on this repo. Configure here.